﻿using Service.Framework.Utils.Extension;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Writers;
using System.Text;

namespace Service.Core.Utils;

public class SharpCompressUtil
{
    /// <summary>
    /// 解压压缩包文件
    /// </summary>
    public static List<(string Name, byte[] bytes)> UnzipFiles(System.IO.Stream stream)
    {
        SharpCompress.Common.ArchiveEncoding ArchiveEncoding = new SharpCompress.Common.ArchiveEncoding();
        SharpCompress.Readers.ReaderOptions options = new SharpCompress.Readers.ReaderOptions();
        options.ArchiveEncoding.Default = Encoding.GetEncoding("gb2312");

        List<(string Name, byte[] bytes)> result = new List<(string Name, byte[] bytes)>();
        using (var archive = ArchiveFactory.Open(stream, options))
        {
            foreach (var entry in archive.Entries)
            {
                if (!entry.IsDirectory)
                {
                    using (var streamResult = new MemoryStream())
                    {
                        entry.WriteTo(streamResult);
                        result.Add((entry.Key, streamResult.ToArray()));
                    }
                }
            }

            return result;
        }
    }


    /// <summary>
    /// 将多个文件压缩到一个文件流中，可保存为zip文件，方便于web方式下载
    /// </summary>
    /// <param name="files">多个文件路径，文件或文件夹，或网络路径http/https</param>
    /// <param name="rootdir"></param>
    /// <returns>文件流</returns>
    public static MemoryStream ZipStream(List<string> files, string rootdir = "")
    {
        using (var archive = CreateZipArchive(files, rootdir))
        {
            var ms = new MemoryStream();
            archive.SaveTo(ms, new WriterOptions(CompressionType.Deflate)
            {
                LeaveStreamOpen = true,
                ArchiveEncoding = new ArchiveEncoding()
                {
                    Default = Encoding.UTF8
                }
            });
            ms.Position = 0;
            return ms;
        }
    }

    private static ZipArchive CreateZipArchive(List<string> files, string rootdir)
    {
        var archive = ZipArchive.Create();
        var dic = GetFileEntryMaps(files);
        foreach (var fileEntry in dic)
        {
            archive.AddEntry(Path.Combine(rootdir, fileEntry.Value), fileEntry.Key);
        }

        return archive;
    }


    /// <summary>
    /// 获取文件路径和zip-entry的映射
    /// </summary>
    /// <param name="files"></param>
    /// <returns></returns>
    private static Dictionary<string, string> GetFileEntryMaps(List<string> files)
    {
        List<string> fileList = new List<string>();

        void GetFilesRecurs(string path)
        {
            //遍历目标文件夹的所有文件
            foreach (string fileName in Directory.GetFiles(path))
            {
                fileList.Add(fileName);
            }

            //遍历目标文件夹的所有文件夹
            foreach (string directory in Directory.GetDirectories(path))
            {
                GetFilesRecurs(directory);
            }
        }

        files.Where(s => !s.StartsWith("http")).ForEach(s =>
        {
            if (Directory.Exists(s))
            {
                GetFilesRecurs(s);
            }
            else
            {
                fileList.Add(s);
            }
        });
        if (!fileList.Any())
        {
            return new Dictionary<string, string>();
        }

        String dirname = Path.GetDirectoryName(fileList.First());
        Dictionary<string, string> dic = fileList.ToDictionary(s => s, s => s.Substring(dirname.Length));
        return dic;
    }
}